#include <stdlib.h>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "../../Common/Utility/Timer.h"
#include "../../Common/Geometry/BSpline.h"

#include <iostream>
#include <iomanip>

#pragma comment(lib, "opencv_core242d")
#pragma comment(lib, "opencv_imgproc242d")
#pragma comment(lib, "opencv_highgui242d")

using namespace cv;
using namespace std;

void main()
{
	int n, t;
	n = 5;			// number of control points - 1
	t = 4;			// degree + 1
	int pointsCnt = 100;

	SplinePoint * spts;          // allocate our control point array
	
	spts= new SplinePoint[n+1];
	
	int SizeX = 800;
	int SizeY = 500;
	int mul = 1;
	int yVarBorder = 50;
	int xVarBorder = 20;
	int yOffset = 30;
	vector<double> yValues;

	for (int i=0; i<=n; i++)  // assign the control points randomly
	{
		double koeff = SizeY / n * i;
		yValues.push_back(pow(koeff,4));
	}

	sort(yValues.begin(), yValues.end());
	srand(clock());

	for (int i=0; i<=n; i++)  // assign the control points randomly
	{
		int variation = rand()%xVarBorder - xVarBorder/2;
		if(i == 0)
		{
			spts[i].x = SizeX/n * i + 10;
		}
		else
		{
			spts[i].x = SizeX/n * i + variation;
		}
		
		
		variation = rand()%yVarBorder - yVarBorder/2;
		if(i == 0)
			variation = 0;

		double value = (yValues[i]/yValues[n] * (SizeY-yOffset-20) ) + variation + yOffset; 

		spts[i].y = value;
		spts[i].z = 0.0f;
	}

	Mat img = Mat::zeros((int)(SizeY * 1.2), (int)(SizeX * 1.2), CV_8UC3);

	for(int i = 0; i <= n; i++)
	{
		circle( img, Point((int)spts[i].x, (int)spts[i].y), 3, CV_RGB( 255, 0, 0), 2, 3);
	}
	
	BSpline bs(t, spts, n + 1);
	SplinePoint * ponts = bs.CalcPoints(pointsCnt);
	
	cout << "Control points:\t\t\t" << n + 1 << endl;
	cout << "BSpline degree:\t\t\t" << t - 1 << endl;
	cout << "Generated BSpline points:\t" << pointsCnt << endl;
	
	for(int i = 0; i < pointsCnt; i++)
	{
		circle( img, Point((int)ponts[i].x, (int)ponts[i].y), 1, CV_RGB( 255, 255, 0), 1, 1);
	}

	imshow("BSpline", img);
	waitKey();
}
